<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">

<head>
    <!-- Book generated using mdBook -->
    <meta charset="UTF-8">
    <title>可变长度数量 - exercisms.io 快速练习</title>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <meta name="description" content="exercisms 的练习，网页版.">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="theme-color" content="#ffffff" />

    <link rel="shortcut icon" href="../favicon.png">
    <link rel="stylesheet" href="../css/variables.css">
    <link rel="stylesheet" href="../css/general.css">
    <link rel="stylesheet" href="../css/chrome.css">
    <link rel="stylesheet" href="../css/print.css" media="print">

    <!-- Fonts -->
    <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
    <link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800"
        rel="stylesheet" type="text/css">
    <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">

    <!-- Highlight.js Stylesheets -->
    <link rel="stylesheet" href="../highlight.css">
    <link rel="stylesheet" href="../tomorrow-night.css">
    <link rel="stylesheet" href="../ayu-highlight.css">

    <!-- Custom theme stylesheets -->
    
    <link rel="stylesheet" href="../theme/custom.css">
    

    
</head>

<body class="light">
    <!-- Provide site root to javascript -->
    <script type="text/javascript">var path_to_root = "../";</script>

    <!-- Work around some values being stored in localStorage wrapped in quotes -->
    <script type="text/javascript">
        try {
            var theme = localStorage.getItem('mdbook-theme');
            var sidebar = localStorage.getItem('mdbook-sidebar');

            if (theme.startsWith('"') && theme.endsWith('"')) {
                localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
            }

            if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
            }
        } catch (e) { }
    </script>

    <!-- Set the theme before any content is loaded, prevents flash -->
    <script type="text/javascript">
        var theme;
        try { theme = localStorage.getItem('mdbook-theme'); } catch (e) { }
        if (theme === null || theme === undefined) { theme = 'light'; }
        document.body.className = theme;
        document.querySelector('html').className = theme + ' js';
    </script>

    <!-- Hide / unhide sidebar before it is displayed -->
    <script type="text/javascript">
        var html = document.querySelector('html');
        var sidebar = 'hidden';
        if (document.body.clientWidth >= 1080) {
            try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch (e) { }
            sidebar = sidebar || 'visible';
        }
        html.classList.remove('sidebar-visible');
        html.classList.add("sidebar-" + sidebar);
    </script>

    <nav id="sidebar" class="sidebar" aria-label="Table of contents">
        <ol class="chapter"><li><a href="../index.html"><strong aria-hidden="true">1.</strong> 超过 88 道练习，任点</a></li><li><a href="../low.html"><strong aria-hidden="true">2.</strong> 易</a></li><li><ol class="section"><li><a href="../hello-world/README.zh.html"><strong aria-hidden="true">2.1.</strong> hello world</a></li><li><a href="../gigasecond/README.zh.html"><strong aria-hidden="true">2.2.</strong> 千兆秒 &gt;&lt; Gigasecond)</a></li><li><a href="../leap/README.zh.html"><strong aria-hidden="true">2.3.</strong> 闰年 &gt;&lt; Leap</a></li><li><a href="../raindrops/README.zh.html"><strong aria-hidden="true">2.4.</strong> 雨滴声 &gt;&lt; Raindrops</a></li><li><a href="../reverse-string/README.zh.html"><strong aria-hidden="true">2.5.</strong> 反转字符串 &gt;&lt; Reverse String</a></li><li><a href="../nth-prime/README.zh.html"><strong aria-hidden="true">2.6.</strong> 第 n 个素数 &gt;&lt; Nth Prime</a></li><li><a href="../bob/README.zh.html"><strong aria-hidden="true">2.7.</strong> 迟钝孩子 &gt;&lt; Bob</a></li><li><a href="../beer-song/README.zh.html"><strong aria-hidden="true">2.8.</strong> 啤酒之歌 &gt;&lt; Beer Song</a></li><li><a href="../proverb/README.zh.html"><strong aria-hidden="true">2.9.</strong> 谚语串烧 &gt;&lt; Proverb</a></li><li><a href="../difference-of-squares/README.zh.html"><strong aria-hidden="true">2.10.</strong> 平方差 &gt;&lt; Difference Of Squares</a></li><li><a href="../sum-of-multiples/README.zh.html"><strong aria-hidden="true">2.11.</strong> 倍数之和 &gt;&lt; Sum Of Multiples</a></li><li><a href="../grains/README.zh.html"><strong aria-hidden="true">2.12.</strong> 谷物 &gt;&lt; Grains</a></li><li><a href="../pythagorean-triplet/README.zh.html"><strong aria-hidden="true">2.13.</strong> 勾股数 &gt;&lt; Pythagorean Triplet</a></li><li><a href="../prime-factors/README.zh.html"><strong aria-hidden="true">2.14.</strong> 素数因子 &gt;&lt; Prime Factors</a></li><li><a href="../series/README.zh.html"><strong aria-hidden="true">2.15.</strong> 子串 &gt;&lt; Series</a></li><li><a href="../armstrong-numbers/README.zh.html"><strong aria-hidden="true">2.16.</strong> 水仙花数 &gt;&lt; Armstrong Numbers</a></li><li><a href="../collatz-conjecture/README.zh.html"><strong aria-hidden="true">2.17.</strong> 3n+1 猜想 &gt;&lt; Collatz Conjecture</a></li><li><a href="../diffie-hellman/README.zh.html"><strong aria-hidden="true">2.18.</strong> 迪菲-赫尔曼密钥交换 &gt;&lt; Diffie Hellman</a></li></ol></li><li><a href="../medium.html"><strong aria-hidden="true">3.</strong> 中等</a></li><li><ol class="section"><li><a href="../saddle-points/README.zh.html"><strong aria-hidden="true">3.1.</strong> 鞍点 &gt;&lt; Saddle Points</a></li><li><a href="../isogram/README.zh.html"><strong aria-hidden="true">3.2.</strong> 等值线 &gt;&lt; Isogram</a></li><li><a href="../say/README.zh.html"><strong aria-hidden="true">3.3.</strong> 英文说数字 &gt;&lt; Say</a></li><li><a href="../run-length-encoding/README.zh.html"><strong aria-hidden="true">3.4.</strong> 游程编码 &gt;&lt; Run Length Encoding</a></li><li><a href="../isbn-verifier/README.zh.html"><strong aria-hidden="true">3.5.</strong> 图书编号 &gt;&lt; ISBN Verifier</a></li><li><a href="../perfect-numbers/README.zh.html"><strong aria-hidden="true">3.6.</strong> 数字也能分类 &gt;&lt; Perfect Numbers</a></li><li><a href="../clock/README.zh.html"><strong aria-hidden="true">3.7.</strong> 时钟 &gt;&lt; Clock</a></li><li><a href="../dot-dsl/README.zh.html"><strong aria-hidden="true">3.8.</strong> DOT DSL</a></li><li><a href="../hamming/README.zh.html"><strong aria-hidden="true">3.9.</strong> 汉明距离 &gt;&lt; Hamming</a></li><li><a href="../simple-linked-list/README.zh.html"><strong aria-hidden="true">3.10.</strong> 简单链表 &gt;&lt; Simple Linked List</a></li><li><a href="../pascals-triangle/README.zh.html"><strong aria-hidden="true">3.11.</strong> 杨辉三角形 &gt;&lt; Pascal's Triangle</a></li><li><a href="../scrabble-score/README.zh.html"><strong aria-hidden="true">3.12.</strong> 字母的分数游戏 &gt;&lt; Scrabble Score</a></li><li><a href="../pangram/README.zh.html"><strong aria-hidden="true">3.13.</strong> 全字母句 &gt;&lt; Pangram</a></li><li><a href="../paasio/README.zh.html"><strong aria-hidden="true">3.14.</strong> PaaS-IO-报告 &gt;&lt; Paasio</a></li><li><a href="../nucleotide-count/README.zh.html"><strong aria-hidden="true">3.15.</strong> 核苷酸计数 &gt;&lt; Nucleotide Count</a></li><li><a href="../luhn/README.zh.html"><strong aria-hidden="true">3.16.</strong> 模 10 算法 &gt;&lt; Luhn</a></li><li><a href="../largest-series-product/README.zh.html"><strong aria-hidden="true">3.17.</strong> 最大数字子串乘积 &gt;&lt; Largest Series Product</a></li><li><a href="../word-count/README.zh.html"><strong aria-hidden="true">3.18.</strong> 单词计数 &gt;&lt; Word Count</a></li><li><a href="../atbash-cipher/README.zh.html"><strong aria-hidden="true">3.19.</strong> Atbash 加密 &gt;&lt; Atbash Cipher</a></li><li><a href="../crypto-square/README.zh.html"><strong aria-hidden="true">3.20.</strong> 密码矩形 &gt;&lt; Crypto Square</a></li><li><a href="../rotational-cipher/README.zh.html"><strong aria-hidden="true">3.21.</strong> 旋转密码 &gt;&lt; Rotational Cipher</a></li><li><a href="../simple-cipher/README.zh.html"><strong aria-hidden="true">3.22.</strong> 简单加密 &gt;&lt; Simple Cipher</a></li><li><a href="../rail-fence-cipher/README.zh.html"><strong aria-hidden="true">3.23.</strong> 栅栏密码 &gt;&lt; Rail Fence Cipher</a></li><li><a href="../etl/README.zh.html"><strong aria-hidden="true">3.24.</strong> ETL</a></li><li><a href="../accumulate/README.zh.html"><strong aria-hidden="true">3.25.</strong> 集合操作 &gt;&lt; Accumulate</a></li><li><a href="../acronym/README.zh.html"><strong aria-hidden="true">3.26.</strong> 术语 &gt;&lt; Acronym</a></li><li><a href="../sieve/README.zh.html"><strong aria-hidden="true">3.27.</strong> 素数筛 &gt;&lt; Sieve</a></li><li><a href="../rna-transcription/README.zh.html"><strong aria-hidden="true">3.28.</strong> RNA 转录 &gt;&lt; RNA Transcription</a></li><li><a href="../triangle/README.zh.html"><strong aria-hidden="true">3.29.</strong> 三角形</a></li><li><a href="../roman-numerals/README.zh.html"><strong aria-hidden="true">3.30.</strong> 罗马数字 &gt;&lt; Roman Numerals</a></li><li><a href="../all-your-base/README.zh.html"><strong aria-hidden="true">3.31.</strong> 你所的基本</a></li><li><a href="../grade-school/README.zh.html"><strong aria-hidden="true">3.32.</strong> 学册</a></li><li><a href="../binary-search/README.zh.html"><strong aria-hidden="true">3.33.</strong> 二分查找</a></li><li><a href="../robot-simulator/README.zh.html"><strong aria-hidden="true">3.34.</strong> 机器人模拟器</a></li><li><a href="../bracket-push/README.zh.html"><strong aria-hidden="true">3.35.</strong> 括号配套</a></li><li><a href="../luhn-from/README.zh.html"><strong aria-hidden="true">3.36.</strong> Luhn From</a></li><li><a href="../queen-attack/README.zh.html"><strong aria-hidden="true">3.37.</strong> 皇后 攻击</a></li><li><a href="../bowling/README.zh.html"><strong aria-hidden="true">3.38.</strong> 保龄球</a></li><li><a href="../sublist/README.zh.html"><strong aria-hidden="true">3.39.</strong> 子列表</a></li><li><a href="../space-age/README.zh.html"><strong aria-hidden="true">3.40.</strong> 地球年</a></li><li><a href="../luhn-trait/README.zh.html"><strong aria-hidden="true">3.41.</strong> Luhn Trait</a></li><li><a href="../macros/README.zh.html"><strong aria-hidden="true">3.42.</strong> 宏</a></li><li><a href="../allergies/README.zh.html"><strong aria-hidden="true">3.43.</strong> 过敏</a></li><li><a href="../variable-length-quantity/README.zh.html" class="active"><strong aria-hidden="true">3.44.</strong> 可变长度数量</a></li><li><a href="../phone-number/README.zh.html"><strong aria-hidden="true">3.45.</strong> 电话号码</a></li><li><a href="../wordy/README.zh.html"><strong aria-hidden="true">3.46.</strong> 罗唆</a></li><li><a href="../tournament/README.zh.html"><strong aria-hidden="true">3.47.</strong> 比赛</a></li><li><a href="../custom-set/README.zh.html"><strong aria-hidden="true">3.48.</strong> 自定义 set</a></li><li><a href="../alphametics/README.zh.html"><strong aria-hidden="true">3.49.</strong> 字母谜题</a></li><li><a href="../two-bucket/README.zh.html"><strong aria-hidden="true">3.50.</strong> 两个桶</a></li><li><a href="../pig-latin/README.zh.html"><strong aria-hidden="true">3.51.</strong> 猪的拉丁文</a></li><li><a href="../diamond/README.zh.html"><strong aria-hidden="true">3.52.</strong> 钻石</a></li><li><a href="../spiral-matrix/README.zh.html"><strong aria-hidden="true">3.53.</strong> 螺旋矩阵</a></li><li><a href="../palindrome-products/README.zh.html"><strong aria-hidden="true">3.54.</strong> 回文产品</a></li><li><a href="../poker/README.zh.html"><strong aria-hidden="true">3.55.</strong> 扑克</a></li><li><a href="../grep/README.zh.html"><strong aria-hidden="true">3.56.</strong> grep</a></li><li><a href="../scale-generator/README.zh.html"><strong aria-hidden="true">3.57.</strong> 音阶生成器</a></li><li><a href="../decimal/README.zh.html"><strong aria-hidden="true">3.58.</strong> 十进制</a></li><li><a href="../anagram/README.zh.html"><strong aria-hidden="true">3.59.</strong> 字谜</a></li><li><a href="../protein-translation/README.zh.html"><strong aria-hidden="true">3.60.</strong> 蛋白质翻译</a></li><li><a href="../robot-name/README.zh.html"><strong aria-hidden="true">3.61.</strong> 机器人名称</a></li><li><a href="../book-store/README.zh.html"><strong aria-hidden="true">3.62.</strong> 书店</a></li></ol></li><li><a href="../high.html"><strong aria-hidden="true">4.</strong> 难</a></li><li><ol class="section"><li><a href="../ocr-numbers/README.zh.html"><strong aria-hidden="true">4.1.</strong> OCR 号码</a></li><li><a href="../minesweeper/README.zh.html"><strong aria-hidden="true">4.2.</strong> 扫雷</a></li><li><a href="../dominoes/README.zh.html"><strong aria-hidden="true">4.3.</strong> 骨牌</a></li><li><a href="../parallel-letter-frequency/README.zh.html"><strong aria-hidden="true">4.4.</strong> 并行字母频率</a></li><li><a href="../rectangles/README.zh.html"><strong aria-hidden="true">4.5.</strong> 矩形</a></li><li><a href="../forth/README.zh.html"><strong aria-hidden="true">4.6.</strong> Forth</a></li><li><a href="../circular-buffer/README.zh.html"><strong aria-hidden="true">4.7.</strong> 循环缓冲区</a></li><li><a href="../react/README.zh.html"><strong aria-hidden="true">4.8.</strong> React</a></li></ol></li><li><a href="../untag.html"><strong aria-hidden="true">5.</strong> 未标签</a></li><li><ol class="section"><li><a href="../hexadecimal/README.zh.html"><strong aria-hidden="true">5.1.</strong> 十六进制</a></li><li><a href="../nucleotide-codons/README.zh.html"><strong aria-hidden="true">5.2.</strong> 核苷酸密码子</a></li><li><a href="../two-fer/README.zh.html"><strong aria-hidden="true">5.3.</strong> two-fer</a></li><li class="spacer"></li></ol></li><li><a href="../add-test-code.html">修改 mdBook 主题</a></li></ol>
    </nav>

    <div id="page-wrapper" class="page-wrapper">

        <div class="page">
            
            <div id="menu-bar" class="menu-bar">
                <div id="menu-bar-sticky-container">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents"
                            aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <!-- START - Rust Cookbook customization -->
                        <button id="edit-button" class="icon-button" type="button" title="Fork and edit" aria-label="Fork and edit"
                            aria-haspopup="true" aria-expanded="false" aria-controls="edit">
                            <i class="fa fa-edit">Edit</i>
                        </button>
                        <!-- END - Rust Cookbook customization -->
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme"
                            aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light <span class="default">(default)</span></button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)"
                            aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                        
                    </div>

                    <h1 class="menu-title">exercisms.io 快速练习</h1>
                    
                        <div class="right-buttons">
                            <a href="../print.html" title="Print this book" aria-label="Print this book">
                                <i id="print-button" class="fa fa-print"></i>
                            </a>
                            
                        </div>
                    </div>
                </div>

            
            <div id="search-wrapper" class="hidden">
                <form id="searchbar-outer" class="searchbar-outer">
                    <input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..."
                        aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                </form>
                <div id="searchresults-outer" class="searchresults-outer hidden">
                    <div id="searchresults-header" class="searchresults-header"></div>
                    <ul id="searchresults">
                    </ul>
                </div>
            </div>
            

            <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
            <script type="text/javascript">
                document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                Array.from(document.querySelectorAll('#sidebar a')).forEach(function (link) {
                    link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                });
            </script>

            <!-- // START - Rust Cookbook customization -->
            <script>
                document.getElementById("edit-button").addEventListener("click", function () {
                    var editWindow = window.open("https://github.com/chinanf-boy/exercism-rust-zh/edit/master/src/variable-length-quantity/README.zh.md");
                });</script>
            <!-- // END - Rust Cookbook customization -->

            <div id="content" class="content">
                <main>
                    <a class="header" href="#variable-length-quantity" id="variable-length-quantity"><h1>Variable Length Quantity</h1></a>
<a class="header" href="#1-readme" id="1-readme"><h2>1. Readme</h2></a>
<a class="header" href="#可变长度数量" id="可变长度数量"><h1>可变长度数量</h1></a>
<p>实现可变长度数量编码和解码.</p>
<p>这项工作的目标是实现<a href="https://en.wikipedia.org/wiki/Variable-length_quantity">VLQ</a>的编码/解码。</p>
<p>简而言之，此编码的目标是以节省字节的方式，对整数值进行编码。只有每个字节的前 7 位是有效的(右对齐；有点像 ASCII 字节)。因此，如果您有 32 位值，则必须解开为一系列 7 位字节。当然，根据您的整数，您将拥有可变数量的字节。要指出哪个是系列的最后一个字节，请将 #7 位清零。而所有前面的字节中，您都要设置#7 位。</p>
<p>所以，如果一个整数介于<code>0-127</code>，它可以表示为一个字节。虽然 VLQ 可以处理任意大小的数字，但对于本练习，我们将仅限于适合 32 位无符号整数的数字。以下是整数作为 32 位值的示例，以及它们转换为的可变长度数量:</p>
<pre><code class="language-text"> NUMBER        VARIABLE QUANTITY
00000000              00
00000040              40
0000007F              7F
00000080             81 00
00002000             C0 00
00003FFF             FF 7F
00004000           81 80 00
00100000           C0 80 00
001FFFFF           FF FF 7F
00200000          81 80 80 00
08000000          C0 80 80 00
0FFFFFFF          FF FF FF 7F
</code></pre>
<a class="header" href="#资源" id="资源"><h2>资源</h2></a>
<p>一个糟糕的 Splice 开发人员，必须实现 MIDI 编码/解码.<a href="https://splice.com">https://splice.com</a></p>
<a class="header" href="#2-开始你的表演" id="2-开始你的表演"><h2>2. 开始你的表演</h2></a>
<pre><pre class="playpen"><code class="language-rust editable">#[derive(Debug, PartialEq)]
pub enum Error {
   IncompleteNumber,
   Overflow,
}

/// Convert a list of numbers to a stream of bytes encoded with variable length encoding.
pub fn to_bytes(values: &amp;[u32]) -&gt; Vec&lt;u8&gt; {
   unimplemented!(&quot;Convert the values {:?} to a list of bytes&quot;, values)
}

/// Given a stream of bytes, extract all numbers which are encoded in there.
pub fn from_bytes(bytes: &amp;[u8]) -&gt; Result&lt;Vec&lt;u32&gt;, Error&gt; {
   unimplemented!(&quot;Convert the list of bytes {:?} to a list of numbers&quot;, bytes)
}

</code></pre></pre>
<a class="header" href="#3-测试代码查看" id="3-测试代码查看"><h2>3. 测试代码查看</h2></a>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[test]
fn to_single_byte() {
   assert_eq!(&amp;[0x00], to_bytes(&amp;[0x00]).as_slice());
   assert_eq!(&amp;[0x40], to_bytes(&amp;[0x40]).as_slice());
   assert_eq!(&amp;[0x7f], to_bytes(&amp;[0x7f]).as_slice());
}

#[test]
//#[ignore]
fn to_double_byte() {
   assert_eq!(&amp;[0x81, 0x00], to_bytes(&amp;[0x80]).as_slice());
   assert_eq!(&amp;[0xc0, 0x00], to_bytes(&amp;[0x2000]).as_slice());
   assert_eq!(&amp;[0xff, 0x7f], to_bytes(&amp;[0x3fff]).as_slice());
}

#[test]
//#[ignore]
fn to_triple_byte() {
   assert_eq!(&amp;[0x81, 0x80, 0x00], to_bytes(&amp;[0x4000]).as_slice());
   assert_eq!(&amp;[0xc0, 0x80, 0x00], to_bytes(&amp;[0x10_0000]).as_slice());
   assert_eq!(&amp;[0xff, 0xff, 0x7f], to_bytes(&amp;[0x1f_ffff]).as_slice());
}

#[test]
//#[ignore]
fn to_quadruple_byte() {
   assert_eq!(&amp;[0x81, 0x80, 0x80, 0x00], to_bytes(&amp;[0x20_0000]).as_slice());
   assert_eq!(
       &amp;[0xc0, 0x80, 0x80, 0x00],
       to_bytes(&amp;[0x0800_0000]).as_slice()
   );
   assert_eq!(
       &amp;[0xff, 0xff, 0xff, 0x7f],
       to_bytes(&amp;[0x0fff_ffff]).as_slice()
   );
}

#[test]
//#[ignore]
fn to_quintuple_byte() {
   assert_eq!(
       &amp;[0x81, 0x80, 0x80, 0x80, 0x00],
       to_bytes(&amp;[0x1000_0000]).as_slice()
   );
   assert_eq!(
       &amp;[0x8f, 0xf8, 0x80, 0x80, 0x00],
       to_bytes(&amp;[0xff00_0000]).as_slice()
   );
   assert_eq!(
       &amp;[0x8f, 0xff, 0xff, 0xff, 0x7f],
       to_bytes(&amp;[0xffff_ffff]).as_slice()
   );
}

#[test]
//#[ignore]
fn from_bytes_test() {
   assert_eq!(Ok(vec![0x7f]), from_bytes(&amp;[0x7f]));
   assert_eq!(Ok(vec![0x2000]), from_bytes(&amp;[0xc0, 0x00]));
   assert_eq!(Ok(vec![0x1f_ffff]), from_bytes(&amp;[0xff, 0xff, 0x7f]));
   assert_eq!(Ok(vec![0x20_0000]), from_bytes(&amp;[0x81, 0x80, 0x80, 0x00]));
   assert_eq!(
       Ok(vec![0xffff_ffff]),
       from_bytes(&amp;[0x8f, 0xff, 0xff, 0xff, 0x7f])
   );
}

#[test]
//#[ignore]
fn to_bytes_multiple_values() {
   assert_eq!(&amp;[0x40, 0x7f], to_bytes(&amp;[0x40, 0x7f]).as_slice());
   assert_eq!(
       &amp;[0x81, 0x80, 0x00, 0xc8, 0xe8, 0x56],
       to_bytes(&amp;[0x4000, 0x12_3456]).as_slice()
   );
   assert_eq!(
       &amp;[
           0xc0, 0x00, 0xc8, 0xe8, 0x56, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0x81, 0x80,
           0x00,
       ],
       to_bytes(&amp;[0x2000, 0x12_3456, 0x0fff_ffff, 0x00, 0x3fff, 0x4000]).as_slice()
   );
}

#[test]
//#[ignore]
fn from_bytes_multiple_values() {
   assert_eq!(
       Ok(vec![0x2000, 0x12_3456, 0x0fff_ffff, 0x00, 0x3fff, 0x4000]),
       from_bytes(&amp;[
           0xc0, 0x00, 0xc8, 0xe8, 0x56, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0x81, 0x80,
           0x00,
       ])
   );
}

#[test]
//#[ignore]
fn incomplete_byte_sequence() {
   assert_eq!(Err(Error::IncompleteNumber), from_bytes(&amp;[0xff]));
}

#[test]
//#[ignore]
fn zero_incomplete_byte_sequence() {
   assert_eq!(Err(Error::IncompleteNumber), from_bytes(&amp;[0x80]));
}

#[test]
//#[ignore]
fn overflow_u32() {
   assert_eq!(
       Err(Error::Overflow),
       from_bytes(&amp;[0xff, 0xff, 0xff, 0xff, 0x7f])
   );
}

#[test]
//#[ignore]
fn chained_execution_is_identity() {
   let test = &amp;[0xf2, 0xf6, 0x96, 0x9c, 0x3b, 0x39, 0x2e, 0x30, 0xb3, 0x24];
   assert_eq!(Ok(Vec::from(&amp;test[..])), from_bytes(&amp;to_bytes(test)));
}

#}</code></pre></pre>
<a class="header" href="#4-答案" id="4-答案"><h2>4. 答案</h2></a>
<p><details></p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[derive(Debug, PartialEq)]
pub enum Error {
   IncompleteNumber,
   Overflow,
}

/// Convert a list of numbers to a stream of bytes encoded with variable length encoding.
pub fn to_bytes(values: &amp;[u32]) -&gt; Vec&lt;u8&gt; {
   let mut res = vec![];

   for value in values {
       res.append(&amp;mut to_bytes_single(*value));
   }
   res
}

fn to_bytes_single(mut value: u32) -&gt; Vec&lt;u8&gt; {
   // over allocates, but avoids growth
   let mut res = Vec::with_capacity(4);

   // 0 must be handled specially, because we need to push one byte
   if value == 0 {
       return vec![0];
   }

   while value &gt; 0 {
       // take the lower 7 bits
       let mut tmp = (value &amp; 0x7f) as u8;
       // remove them from the original value
       value &gt;&gt;= 7;

       // set continuation bit
       if !res.is_empty() {
           tmp |= 0x80;
       }

       res.push(tmp);
   }

   // order is wrong due to the way we pushed the data onto it
   res.reverse();
   res
}

// Alternative solution with hardcoded borders
// /// Convert a list of numbers to a stream of bytes encoded with variable length encoding.
// pub fn to_bytes(values: &amp;[u32]) -&gt; Vec&lt;u8&gt; {
//     let mut res = vec![];
//
//     for &amp;value in values {
//         if value &lt;= 0x7f {
//             res.push(value as u8);
//         } else if value &lt;= 0x3fff {
//             res.push(((value &gt;&gt; 7) &amp; 0xff) as u8 | 0x80);
//             res.push((value &amp; 0x7f) as u8);
//         } else if value &lt;= 0x1f_ffff {
//             res.push(((value &gt;&gt; 14) &amp; 0xff) as u8 | 0x80);
//             res.push(((value &gt;&gt; 7) &amp; 0xff) as u8 | 0x80);
//             res.push((value &amp; 0x7f) as u8);
//         } else if value &lt;= 0x0fff_ffff {
//             res.push(((value &gt;&gt; 21) &amp; 0xff) as u8 | 0x80);
//             res.push(((value &gt;&gt; 14) &amp; 0xff) as u8 | 0x80);
//             res.push(((value &gt;&gt; 7) &amp; 0xff) as u8 | 0x80);
//             res.push((value &amp; 0x7f) as u8);
//         } else {
//             res.push(((value &gt;&gt; 28) &amp; 0xff) as u8 | 0x80);
//             res.push(((value &gt;&gt; 21) &amp; 0xff) as u8 | 0x80);
//             res.push(((value &gt;&gt; 14) &amp; 0xff) as u8 | 0x80);
//             res.push(((value &gt;&gt; 7) &amp; 0xff) as u8 | 0x80);
//             res.push((value &amp; 0x7f) as u8);
//         }
//     }
//     res
// }

/// Given a stream of bytes, extract all numbers which are encoded in there.
pub fn from_bytes(bytes: &amp;[u8]) -&gt; Result&lt;Vec&lt;u32&gt;, Error&gt; {
   let mut res = vec![];
   let mut tmp = 0;
   for (i, b) in bytes.iter().enumerate() {
       // test if first 7 bit are set, to check for overflow
       if (tmp &amp; 0xfe_00_00_00) &gt; 0 {
           return Err(Error::Overflow);
       }

       // append bytes of b to tmp
       tmp = (tmp &lt;&lt; 7) | (b &amp; 0x7f) as u32;

       if 0x80 &amp; b == 0 {
           // continuation bit not set, number if complete
           res.push(tmp);
           tmp = 0;
       } else {
           // check for incomplete bytes
           if i + 1 == bytes.len() {
               // the next index would be past the end,
               // i.e. there are no more bytes.
               return Err(Error::IncompleteNumber);
           }
       }
   }

   Ok(res)
}

#}</code></pre></pre>
<p></details></p>
<hr />
<hr />
<a class="header" href="#填充相关" id="填充相关"><h2>填充/相关</h2></a>

                </main>

                <nav class="nav-wrapper" aria-label="Page navigation">
                    <!-- Mobile navigation buttons -->
                    
                    <a rel="prev" href="../allergies/README.zh.html" class="mobile-nav-chapters previous" title="Previous chapter"
                        aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                    

                    
                    <a rel="next" href="../phone-number/README.zh.html" class="mobile-nav-chapters next" title="Next chapter"
                        aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
                    

                    <div style="clear: both"></div>
                </nav>
            </div>
        </div>

        <nav class="nav-wide-wrapper" aria-label="Page navigation">
            
            <a href="../allergies/README.zh.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter"
                aria-keyshortcuts="Left">
                <i class="fa fa-angle-left"></i>
            </a>
            

            
            <a href="../phone-number/README.zh.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter"
                aria-keyshortcuts="Right">
                <i class="fa fa-angle-right"></i>
            </a>
            
        </nav>

    </div>

    

    
    <!-- Google Analytics Tag -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-128555056-1"></script>
    
    <script type="text/javascript">
        var localAddrs = ["localhost", "127.0.0.1", ""];
        if (localAddrs.indexOf(document.location.hostname) === -1) {
            window.dataLayer = window.dataLayer || [];
            function gtag() { dataLayer.push(arguments); }
            gtag('js', new Date());

            gtag('config', 'UA-128555056-1');
        }
    </script>
    

    
    <script src="../ace.js" type="text/javascript" charset="utf-8"></script>
    <script src="../editor.js" type="text/javascript" charset="utf-8"></script>
    <script src="../mode-rust.js" type="text/javascript" charset="utf-8"></script>
    <script src="../theme-dawn.js" type="text/javascript" charset="utf-8"></script>
    <script src="../theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
    

    
    <script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
    

    <script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
    <script src="../book.js" type="text/javascript" charset="utf-8"></script>

    <!-- Custom JS scripts -->
    

    

</body>

</html>